use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum Message {
    #[serde(rename = "broadcast")]
    Broadcast {
        content: String,
        sender_id: Uuid,
        timestamp: u64,
    },
    
    #[serde(rename = "direct")]
    Direct {
        content: String,
        target_id: Uuid,
        sender_id: Uuid,
        timestamp: u64,
    },
    
    #[serde(rename = "join")]
    Join {
        user_id: Uuid,
        username: String,
    },
    
    #[serde(rename = "leave")]
    Leave {
        user_id: Uuid,
    },
    
    #[serde(rename = "ack")]
    Ack {
        message_id: Uuid,
    },
    
    #[serde(rename = "ping")]
    Ping,
    
    #[serde(rename = "pong")]
    Pong,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConnectionInfo {
    pub id: Uuid,
    pub username: String,
    pub connected_at: u64,
    pub last_activity: u64,
}

impl Message {
    pub fn broadcast(content: String, sender_id: Uuid) -> Self {
        Self::Broadcast {
            content,
            sender_id,
            timestamp: current_timestamp(),
        }
    }
    
    pub fn direct(content: String, target_id: Uuid, sender_id: Uuid) -> Self {
        Self::Direct {
            content,
            target_id,
            sender_id,
            timestamp: current_timestamp(),
        }
    }
    
    pub fn to_json(&self) -> Result<String, serde_json::Error> {
        serde_json::to_string(self)
    }
    
    pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
        serde_json::from_str(json)
    }
}

fn current_timestamp() -> u64 {
    std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap()
        .as_secs()
}